/*
** Copyright (C) 2009 Joshua Brent Marsh <joshua@icub3d.com>
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 3 of the License, or
** (at your option) any later version.
**  
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/

/* $Id: test_utilities.c 32 2009-10-28 22:51:19Z joshua@icub3d.com $ */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <malloc.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


#include <CUnit/Basic.h>

#include "../src/utilities.h"

#include "test_utilities.h"

Map *m;

int
init_test_utilities_suite ()
{
  int ret;

  ret = system ("mkdir -p /tmp/test_utilities_conf/conf.d/test/");
  ret = system ("echo '"
		"#this is a comment line\n"
		"#this is also a useless line\n"
		"\t\t\t\t\n"
		"\tName = Joshua#another comment\n"
		"\"equal=sign\" = haha\n"
		"this_is_a=/test\n"
		"cuteness = \"Jennifer = marsh\" #comment here\n"
		"' > /tmp/test_utilities_conf/conf.d/a.conf");

  ret = system ("echo '"
		"\"equal=sign\" = \"haha\n"
		"cuteness = \"Jennifer = marsh\"\n"
		"' > /tmp/test_utilities_conf/b.conf");

  ret = system ("echo '"
		"\"equal=sign\" = haha\n"
		"cuteness \n"
		"' > /tmp/test_utilities_conf/c.conf");

  ret = system ("echo '"
		"\"equal=sign\" = lol\n"
		"' > /tmp/test_utilities_conf/conf.d/d.conf");

  ret = system ("echo '"
		"  cuteness = \"Jennifer Marsh\" \n"
		"new-config = howdy!\n"
		"' > /tmp/test_utilities_conf/conf.d/e.conf");
  ret = system ("echo '"
		"another-config = Yo!\n"
		"' > /tmp/test_utilities_conf/conf.d/test/a.conf");

  ret = system ("mkdir -p /tmp/mkrdir/");

  return 0;
}

int
clean_test_utilities_suite ()
{
  int ret;

  ret = system ("rm -rf /tmp/test_utilities_conf/");
  ret = system ("rm -rf /tmp/mkrdir/");

  return 0;
}

void
test_utilities_load_config ()
{
  Map *m = NULL;

  CU_ASSERT (load_config ("/tmp/test_utilities_conf/b.conf", NULL) == NULL);
  CU_ASSERT (load_config ("/tmp/test_utilities_conf/c.conf", NULL) == NULL);

  m = load_config ("/tmp/test_utilities_conf/conf.d/a.conf", NULL);
  CU_ASSERT (m != NULL);
  CU_ASSERT (strcmp (map_get (m, "Name"), "Joshua") == 0);
  CU_ASSERT (strcmp (map_get (m, "this_is_a"), "/test") == 0);
  CU_ASSERT_STRING_EQUAL (map_get (m, "cuteness"), "Jennifer = marsh");
  CU_ASSERT_STRING_EQUAL (map_get (m, "equal=sign"), "haha");
  map_destroy (m);
}

void
test_utilities_load_configs ()
{
  Map *m = NULL;

  m = load_configs ("/tmp/test_utilities_conf/conf.d/", NULL);
  CU_ASSERT (m != NULL);
  CU_ASSERT_STRING_EQUAL (map_get (m, "Name"), "Joshua");
  CU_ASSERT_STRING_EQUAL (map_get (m, "cuteness"), "Jennifer Marsh");
  CU_ASSERT_STRING_EQUAL (map_get (m, "equal=sign"), "lol");
  CU_ASSERT_STRING_EQUAL (map_get (m, "new-config"), "howdy!");
  CU_ASSERT_STRING_EQUAL (map_get (m, "another-config"), "Yo!");
  map_destroy (m);
}

void
test_utilities_get_segment ()
{
  char *begin, *end, *cur;
  int state;
  char *one = "\"This, is, a, test\",another,and another";
  char *two = "name = value";
  char *three = "\"name=value\" = \"josh=jennifer\"";
  char *four = "\"name value";
  char *five = "this#fail here.";

  cur = one;
  state = get_segment (&cur, &begin, &end, ",", "\"", "");
  CU_ASSERT (state == ISS_END);
  CU_ASSERT (*begin == 'T');
  CU_ASSERT (*end == '"');
  CU_ASSERT (*cur == 'a');
  CU_ASSERT (end - begin == 17);
  CU_ASSERT (strncmp (begin, "This, is, a, test\"", end - begin) == 0);

  cur = two;
  state = get_segment (&cur, &begin, &end, " \t\r\n=", "\"", "#");
  CU_ASSERT (state == ISS_END);
  CU_ASSERT (*begin == 'n');
  CU_ASSERT (*end == ' ');
  CU_ASSERT (*cur == '=');
  CU_ASSERT (end - begin == 4);
  CU_ASSERT (strncmp (begin, "name ", end - begin) == 0);

  cur = three;
  state = get_segment (&cur, &begin, &end, " \t\r\n=", "\"", "#");
  CU_ASSERT (state == ISS_END);
  CU_ASSERT (*begin == 'n');
  CU_ASSERT (*end == '"');
  CU_ASSERT (*cur == '=');
  CU_ASSERT (end - begin == 10);
  CU_ASSERT (strncmp (begin, "name=value\"", end - begin) == 0);

  cur = four;
  state = get_segment (&cur, &begin, &end, " \t\r\n=", "\"", "#");
  CU_ASSERT (state == ISS_FAIL);

  cur = five;
  state = get_segment (&cur, &begin, &end, " \t\r\n=", "\"", "#");
  CU_ASSERT (state == ISS_END);
  CU_ASSERT (*begin == 't');
  CU_ASSERT (*end == '#');
  CU_ASSERT (*cur == '#');
  CU_ASSERT (end - begin == 4);
  CU_ASSERT (strncmp (begin, "this#", end - begin) == 0);
}

void
test_utilities_snumlen ()
{
  CU_ASSERT (snumlen (0, 10) == 1);
  CU_ASSERT (snumlen (0, 8) == 1);
  CU_ASSERT (snumlen (0, 16) == 1);

  CU_ASSERT (snumlen (938147, 10) == 6);
  CU_ASSERT (snumlen (24, 8) == 2);
  CU_ASSERT (snumlen (123456789, 16) == 7);

  CU_ASSERT (snumlen (192938147, 10) == 9);
  CU_ASSERT (snumlen (93824, 8) == 6);
  CU_ASSERT (snumlen (1710, 16) == 3);


  CU_ASSERT (snumlen (93824, 2) == 17);
}

void
test_utilities_ssnumlen ()
{
  CU_ASSERT (ssnumlen (938147, 10, 0) == 6);
  CU_ASSERT (ssnumlen (24, 8, 0) == 2);
  CU_ASSERT (ssnumlen (123456789, 16, 0) == 7);

  CU_ASSERT (ssnumlen (192938147, 10, 1) == 9);
  CU_ASSERT (ssnumlen (-93824, 10, 1) == 6);
  CU_ASSERT (ssnumlen (-1710, 10, 1) == 5);
  CU_ASSERT (ssnumlen (-93824, 8, 0) == 6);
  CU_ASSERT (ssnumlen (-1710, 16, 1) == 4);


  CU_ASSERT (ssnumlen (-93824, 2, 1) == 18);
}

void
test_utilities_mkrdir ()
{
  struct stat st;

  mkrdir ("/tmp/mkrdir/test", S_IRWXU | S_IRWXG);
  CU_ASSERT (stat ("/tmp/mkrdir/test", &st) == 0);
  CU_ASSERT (S_ISDIR(st.st_mode) == 1);
  CU_ASSERT (S_ISREG(st.st_mode) == 0);

  mkrdir ("/tmp/mkrdir//another/test/directory", S_IRWXU | S_IRWXG);
  CU_ASSERT (stat ("/tmp/mkrdir//another/test/directory", &st) == 0);
  CU_ASSERT (S_ISDIR(st.st_mode) == 1);
  CU_ASSERT (S_ISREG(st.st_mode) == 0);

  mkrdir ("/tmp/mkrdir//another//strange//////"
	  "test/directory/for/your///////", S_IRWXU | S_IRWXG);
  CU_ASSERT (stat ("/tmp/mkrdir//another//strange//////"
		   "test/directory/for/your///////", &st) == 0);
  CU_ASSERT (S_ISDIR(st.st_mode) == 1);
  CU_ASSERT (S_ISREG(st.st_mode) == 0);

}

void
test_utilities_execute_shell_command ()
{
  char *res;
  char *args[3];

  args[0] = "cat";
  args[1] = NULL;

  res = execute_shell_command ("cat", args, "This is a test.");
  CU_ASSERT (res != NULL);
  CU_ASSERT (strcmp (res, "This is a test.") == 0);
  free (res);

  args[0] = "echo";
  args[1] = "Hello";
  args[2] = NULL;

  res = execute_shell_command ("echo", args, NULL);
  CU_ASSERT (res != NULL);
  CU_ASSERT (strcmp (res, "Hello\n") == 0);
  free (res);

}

void
test_utilities_check_file_exists ()
{
  CU_ASSERT (check_file_exists ("/tmp/mkrdir/test.txt") == 1);
  CU_ASSERT (check_file_exists ("/tmp/mkrdir/fake_test.txt") == 0);
}

void
test_utilities_write_file ()
{
  char *in;

  CU_ASSERT (write_file ("/tmp/mkrdir/test.txt", "Hello world!") == 1);

  CU_ASSERT ((in = read_file ("/tmp/mkrdir/test.txt")) != NULL);
  
  CU_ASSERT (strcmp (in, "Hello world!") == 0);

  free (in);
}

void
test_utilities_send_email ()
{
  CU_ASSERT (send_email ("/usr/sbin/sendmail -t", "root@localhost", 
			 "root@localhost", "", "Send Email Unit test.",
			 "This is a test of the send_mail utility function. "
			 "%s",
			 "\nThanks,\nJosh") == 1);
}

int
make_utilities_suite (CU_pSuite s)
{
  s = CU_add_suite ("Test Utilities Suite", 
		    init_test_utilities_suite, 
		    clean_test_utilities_suite);
  if (s == NULL)
    return CU_get_error();

  if (CU_add_test (s, "test utilities_load_config", 
		   test_utilities_load_config) == NULL ||
      CU_add_test (s, "test utilities_load_configs", 
		   test_utilities_load_configs) == NULL ||
      CU_add_test (s, "test utilities_get_segment", 
		   test_utilities_get_segment) == NULL ||
      CU_add_test (s, "test utilities_snumlen", 
		   test_utilities_snumlen) == NULL ||
      CU_add_test (s, "test utilities_ssnumlen", 
		   test_utilities_ssnumlen) == NULL ||
      CU_add_test (s, "test utilities_execute_shell_command", 
		   test_utilities_execute_shell_command) == NULL ||
      CU_add_test (s, "test utilities_write_file", 
		   test_utilities_write_file) == NULL ||
      CU_add_test (s, "test utilities_check_file_exists", 
		   test_utilities_check_file_exists) == NULL ||
      CU_add_test (s, "test utilities_send_email", 
		   test_utilities_send_email) == NULL ||
      CU_add_test (s, "test utilities_mkrdir", 
		   test_utilities_mkrdir) == NULL
      )
    {
      return CU_get_error();
    }

  return CU_get_error();

}

